
#pragma once

#include <stdio.h>

#include "core/olisp_core.h"
#include "interpreter/olisp_interpreter.h"

#ifndef LISP_FEAT_QUOTE_SUPPORT
#error this file can be compiled only with quote support enabled 
#endif

typedef struct
{
    /*
     * name of the macro
     */
    id_obj_t *  name;

    /*
     * arguments list - introduced in order to check whether
     * certain macro call is suitable or not
     */
    obj_t *     arg_list;

    /*
     * macro body
     */
    obj_t *     body;
} subst_t;

typedef struct subst_collection_t
{
    /*
     * one another collection to take into an account
     */
    struct subst_collection_t * prev_col;

    /*
     * macro definitions what are resided in current file
     */
    subst_t ** substs;

    size_t length;
    size_t allocated;
} subst_collection_t;

/*
 * represents a context used by macro substitutor
 */
typedef struct
{
    FILE *              stream;

    /*
     * the name of the stream
     */
    const char *        stream_name;

    /*
     * dumps an information about parsing
     * interprets string before macro substitution
     */
    interpreter_t *     interpreter;

    /*
     * represents a quote manager
     */
    lisp_quote_mgr_t *  quote_mgr;

    /*
     * defmacro element name - it will be released
     * if it is non-null - it will be released in dispose_macro_subst_context
     * in case it is left 0 - it will be replaced to the default one argument
     */
    obj_t *       defmacro_name;

    /*
     * if this will be non-null, elements from reader shall append to this
     * before being processed.
     * if it is non-null - it will be released in dispose_macro_subst_context
     */
    list_obj_t *  unprocessed_list;

    /*
     * registered macro definitions
     */
    subst_collection_t defs;
} macro_substitutor_context_t;

/*
 * reads all and performs macro substitution
 */
list_obj_t * macro_read( macro_substitutor_context_t * ctx );

void dispose_macro_subst_context( macro_substitutor_context_t * ctx );
